<?php

class UploadVideo{
	static $change_logs = array();
	static $current_index = '';

	public static function clearExpiredVideoFiles($expire_time=3600){
		exec('find ' . AC::VIDEO_STORE_PATH . ' -name "uploading"',$video_dirs);
		exec('find ' . AC::VIDEO_STORE_PATH . ' -name "json"',   $json_dirs);

		$video_dirs = array_merge($video_dirs,$json_dirs);

		$now_time      = time();
		$expired_files = array();
		
		foreach($video_dirs as $file)
		{
			if(!file_exists($file)) continue;

			$dir_name   = dirname($file);
			$file_ctime = filectime(dirname($dir_name));

			if( ($file_ctime+$expire_time) < $now_time )
			{ 
				$expired_files[] = $file;
			}
		}
		return self::_deleteFiles($expired_files);
	}

	public static function checkWinscpJson(){
		exec('find ' . AC::VIDEO_STORE_PATH . ' -name "json"',$json_dirs);

		$failed = array();
		foreach($json_dirs as $file){
			$json_data = json_decode(file_get_contents($file),1);
			if(empty($json_data['video_id']) || empty($json_data['exports']) || empty($json_data['numVideoFiles'])){
				echo "file:'$file' format error!\n",print_r($json_data,1);
				echo "'video_id','exports' or 'numVideoFiles' is empty\n\n";
				$failed[] = $file;
				continue;
			}

			$exports = explode(',',$json_data['exports']);
			$exports_error = false;
			foreach($exports as $check_export){
				if(!array_key_exists($check_export, AC::$vi_export_params)){
					echo "file:'$file' format error!\n",print_r($json_data,1);
					echo "export:'$check_export' error, export type need in(",implode(',',array_keys(AC::$vi_export_params)),")\n\n";
					$exports_error = true;
					continue;
				}
			}
			if($exports_error){
				$failed[] = $file;
				continue;
			}

			$dir = dirname($file);
			$files = glob( $dir.'/part/*.mp4');
			$image = glob( $dir.'/part/image.*');
			if(empty($image) || count($files) != $json_data['numVideoFiles'])
			{
				echo "file:'$file' format error!\n",print_r($json_data,1);
				echo "Video(*.mp4) files total number not equal 'numVideoFiles' or no Image(image.*) file\n\n";
				$failed[] = $file;
				continue;
			}

			$dir_video_id = substr($dir,strrpos($dir,'/')+1);
			if($json_data['video_id'] != $dir_video_id)
			{
				echo "file:'$file' format error!\n",print_r($json_data,1);
				echo "'video_id' not in the file path\n\n";
				$failed[] = $file;
				continue;
			}

			$acl_data = array();
			$acl_ok  = 0;
			$acl_ok += isset($json_data['publish_datetime']);
			$acl_ok += isset($json_data['expire_datetime']);
			$acl_ok += isset($json_data['country_allow_list']);
			$acl_ok += isset($json_data['country_deny_list']);
			if($acl_ok == 4)
			{

				if(!($publish_time = strtotime($json_data['publish_datetime'])))
				{
					echo "file:'$file' format error!\n",print_r($json_data,1);
					echo "'publish_datetime' is not date\n\n";
					$failed[] = $file;
					continue;
				}

				if(!($expire_time = strtotime($json_data['expire_datetime'])))
				{
					echo "file:'$file' format error!\n",print_r($json_data,1);
					echo "'expire_datetime' is not date\n\n";
					$failed[] = $file;
					continue;
				}
			
				if($expire_time <= $publish_time)
				{
					echo "file:'$file' format error!\n",print_r($json_data,1);
					echo "'publish_datetime' must earlier than 'expire_datetime'\n\n";
					$failed[] = $file;
					continue;
				}

				$allow_is_all = (strcasecmp($json_data['country_allow_list'], 'ALL') == 0);
				$deny_is_all  = (strcasecmp($json_data['country_deny_list'],  'ALL') == 0);
				if( ($allow_is_all && $deny_is_all) || (!$allow_is_all && !$deny_is_all) )
				{
					echo "file:'$file' format error!\n",print_r($json_data,1);
					echo "'country_allow_list' and 'country_deny_list' value must have a 'ALL' and only one is 'ALL'\n\n";
					$failed[] = $file;
					continue;
				}

				if($allow_is_all){
					$json_data['country_allow_list'] = 'ALL';
				}elseif(strcasecmp($json_data['country_allow_list'],'NONE')==0 || $json_data['country_allow_list'] == ''){
					$json_data['country_allow_list'] = '';
				}else{
					$checked_list = array();
					if(!country::checkGaoCountryList($json_data['country_allow_list'],$checked_list)){
						$import = explode(',',$json_data['country_allow_list']);
						echo "file:'$file' format error!\n",print_r($json_data,1);
						echo "'country_allow_list' " , implode(",",array_diff($import,$checked_list)) , " not in database\n\n";
						$failed[] = $file;
						continue;
					}
					$json_data['country_allow_list'] = implode(',',$checked_list);
				}

				if($deny_is_all){
					$json_data['country_deny_list'] = 'ALL';
				}elseif(strcasecmp($json_data['country_deny_list'],'NONE')==0 || $json_data['country_deny_list'] == ''){
					$json_data['country_deny_list'] = '';
				}else{
					$checked_list = array();
					if(!country::checkGaoCountryList($json_data['country_deny_list'],$checked_list)){
						$import = explode(',',$json_data['country_deny_list']);
						echo "file:'$file' format error!\n",print_r($json_data,1);
						echo "'country_deny_list' " , implode(",",array_diff($import,$checked_list)) , " not in database\n\n";
						$failed[] = $file;
						continue;
					}
					$json_data['country_deny_list'] = implode(',',$checked_list);
				}

				$acl_data = array(
					'publish_datetime'  => $json_data['publish_datetime'],
					'expire_datetime'   => $json_data['expire_datetime'],
					'country_allow_list'=> $json_data['country_allow_list'],
					'country_deny_list' => $json_data['country_deny_list']
				);
			}
			else if($acl_ok > 0)
			{
				echo "file:'$file' format error!\n",print_r($json_data,1);
				echo "If have ACL info then 'publish_datetime','expire_datetime','country_allow_list' and 'country_deny_list' not can by empty\n\n";
				$failed[] = $file;
				continue;
			}

			$new_data = array( 'video_id'=>$json_data['video_id'], 'exports'=>$json_data['exports']);

			if(isset($json_data['breakpoints']))
			{
				$new_data['breakpoints'] = $json_data['breakpoints'];
			}

			if($acl_data)
			{
				$new_data['acl'] = $acl_data;
			}
			
			file_put_contents($file, json_encode($new_data));
			rename( $file , $dir . '/finished');
		}
		#self::_renameFiles($failed,'json_check_failed');
		return true;
	}

	public static function upload(){
		exec('find ' . AC::VIDEO_STORE_PATH . ' -name "finished"',$video_dirs);

		$uploaded_files = array();
		$failed = array();

		# change_log
		self::$change_logs = array();

		foreach($video_dirs as $file){
			# change_log
			self::$current_index = md5($file);
			self::$change_logs[self::$current_index] = array();

			$dir = dirname($file);
			$files = glob( $dir.'/part/*.mp4');
			$image = glob( $dir.'/part/image.*');
			$image = $image[0];

			Model::$dbo['w']->beginTransaction();

			try{
				$updated = self::_uploadVideo($image,$files,json_decode(file_get_contents($file),1));
				if($updated){
					$uploaded_files[] = $file;
				}else{
					$failed[] = $file;
				}
				Model::$dbo['w']->commit();
			}catch(Exception $e){
				$failed[] = $file;
				unset(self::$change_logs[self::$current_index]);
				Model::$dbo['w']->rollBack();
			}
		}

		# change_log
		$change_log = array();
		foreach(self::$change_logs as $logs){
			$change_log = array_merge($change_log,$logs);
		}
		array_walk($change_log,'change_log::updateOne');

		#self::_renameFiles($failed,'upload_failed');
		//self::_renameFiles($uploaded_files,'uploaded');
		self::_deleteFiles($uploaded_files);
		return true;
	}

	public static function exportVideo($vi_obj, $user_id, $source_id, $export, $video_id, $vi_id,$p_id){
		if(!array_key_exists($export, AC::$vi_export_params)){
			echo 'export type error, export type need in(',implode(',',array_keys(AC::$vi_export_params)),')';
		}

		$vi_params = AC::$vi_export_params[$export];
		if($vi_params['callback_url']){
			$vi_params['callback_url'] = CommonUtils::url_add_param($vi_params['callback_url'],array('video_id'=>$video_id));
		}
		$vi_params = array_values($vi_params);
		array_unshift($vi_params, $user_id, $source_id);
		$export_id = call_user_func_array(array($vi_obj,'requestExport'),$vi_params);
		
		if($export_id > 0){
			$insert_sql = 'INSERT INTO video_export(video_id,vi_id,export_id,export_params,vi_status) VALUES (:vid,:vi_id,:e_id,:pms,:vi_status)';
			Model::updateBySql(
				$insert_sql,
				array(
					':vid'=>$video_id,
					':vi_id'=>$vi_id,
					':e_id'=>$export_id,
					':pms'=>json_encode($vi_params),
					/* set the export status to VIDEO_STATUS_UPLOADED if the callback_url is empty.
					 * #modified by Albie Lu on 2011-11-09# */
					':vi_status'=>$vi_params[13]?(AC::VIDEO_STATUS_WAITING):(AC::VIDEO_STATUS_UPLOADED)
				)
			);

			# change_log
			self::$change_logs[self::$current_index][] = array(
				'type'=>'video_export',
				'keys'=>array('id'=>Model::$dbo['w']->getDbHandle()->lastInsertId()),
				'programme_id' => $p_id,
			);
		}

		return $export_id;
	}

	private static function _uploadVideo($image,$source_files,array $data){
		sort($source_files);

		$video_id  = $data['video_id'];
		$video_obj = Model::$dbo['w']->findInstance('video',$video_id);
		if(!$video_obj) return false;

		// set files array index
		array_unshift($source_files,'');
		unset($source_files[0]);
		
		$uploader  = CommonUtils::get_user();
		$vi_client = new VideoInfrastructureClient();

		// if existing vi_id then delete video
		if($video_obj->vi_id > 0)
		{
			if($video_obj->ii_id > 0){
				$ii_client = new ImageInfrastructureClient();
				$ii_client->deleteSource($video_obj->ii_id);
			}
			$vi_client->deleteSource($video_obj->vi_id);
		}

		$source_id = $vi_client->uploadVideo($uploader, $source_files);
		if($source_id<1)
		{
			$video_obj->vi_status = AC::VIDEO_STATUS_FAILED;
			Model::$dbo['w']->save($video_obj);
			echo "video[$video_id] => Upload video files(", implode(',',$source_files) ,") to VI fail!\n VI Return:$source_id\n";
			return false;
		}
		
		// upload image to II
		$upload_status = CommonUtils::upload_image_to_ii($image);
		$image_uploaded = ( array_sum($upload_status['status']) == count($upload_status['status']) );
		if(!$image_uploaded)
		{
			$video_obj->ii_status = AC::IMAGE_STATUS_FAILED;
			Model::$dbo['w']->save($video_obj);
			echo "video[$video_id] => Upload image file:($image) to II fail!\n\n";
			print_r($upload_status);
			return false;
		}

		// update video table 
		$video_obj->vi_id            = $source_id;
		$video_obj->vi_status        = AC::VIDEO_STATUS_WAITING;
		$video_obj->ii_id            = $upload_status['source_id'];
		$video_obj->ii_status        = $upload_status['ii_status'];
		$video_obj->thumbnail_url    = $upload_status['thumbnail_url'];
		$video_obj->image_source_url = $upload_status['source_url'];
		if(isset($data['acl']) && is_array($data['acl']))
		{
			$video_obj->country_allow_list  = $data['acl']['country_allow_list'];
			$video_obj->country_deny_list   = $data['acl']['country_deny_list'];
			$video_obj->publish_datetime    = $data['acl']['publish_datetime'];
			$video_obj->expire_datetime     = $data['acl']['expire_datetime'];
		}
		Model::$dbo['w']->save($video_obj);

		// send ACL info to VI
		$meta_obj = new UpdateMeta('Video',$video_id);
		$meta_obj->UpdateAcl();

		// update metadata
		if(isset($data['metadata']) && is_array($data['metadata']))
		{
			$ok = $vi_client->updateMeta(
				$source_id, 
				$uploader,
				$data['metadata']['title'], 
				$data['metadata']['person'], 
				$data['metadata']['tag'], 
				$data['metadata']['miscellaneous']
			);

			if(!$ok) echo "video[$video_id] => Warning: Video uploadMeta fail!\n\n";
		}

		// update breakpoints
		if(isset($data['breakpoints']) && $data['breakpoints'])
		{
			 $vi_client->setBreakpoint($source_id,$data['breakpoints']);
		}
		
		//delete old video export of this video
		$sql = "delete from video_export where video_id = :video_id";
		$params = array(":video_id"=>$video_id);
		Model::updateBySql($sql,$params);

		// request export video
		foreach(explode(',',$data['exports']) as $export){
			$export_id = self::exportVideo($vi_client, $uploader, $source_id, $export, $video_id, $source_id,$video_obj->programme_id);
			if($export_id<1)
			{
				$video_obj->vi_status = AC::VIDEO_STATUS_FAILED;
				echo "video[$video_id] => Request export video fail!\n\n";
				Model::$dbo['w']->save($video_obj);
				return false;
			}
		}
		Model::$dbo['w']->save($video_obj);

		# change_log
		self::$change_logs[self::$current_index][] = array(
			'type'=>'video',
			'keys'=>array('id'=>$video_id),
			'programme_id' => $video_obj->programme_id,
		);
		return true;
	}

	private static function _renameFiles(array $files,$new_file_name){
		foreach($files as $file){
			$dir = dirname($file);
			rename($file, $dir.'/'.$new_file_name);
		}
	}

	private static function _deleteFiles(array $files){
		foreach($files as $file){
			$dir = dirname($file);

			$part_files = glob($dir.'/part/*');
			foreach($part_files as $pf){
				unlink($pf);
			}
			rmdir($dir.'/part');
			unlink($file);
			rmdir($dir);
		}
		return true;
	}
}

?>
